/**
 * 
 */
package org.lex.net.ping;

import java.io.IOException;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

import org.lex.utils.LineBasedProcess;
import org.lex.utils.SystemProperties.OS;


/**
 * @author Daniel Liu
 */
public abstract class Ping {
	public static final int PACKET_SIZE = 32;
	public static final int COUNT = 5;
	private String host = "127.0.0.1";
	private int packetSize = 32;
	private int count = 5;
	private EventListenerList listenerList = null;
	// ===========================================
	private LineBasedProcess process = null;
	private ChangeListener changeListener = null;

	public static Ping newInstance(String host) {
		Ping ins = null;
		if (OS.isWindows())
			ins = new WindowsPing(host, PACKET_SIZE, COUNT);
		// else if( OS.)
		return ins;
	}

	protected abstract String[] createPingCommand();

	protected abstract PingEvent parsePingReply(String line);

	protected Ping(String host, int packetSize, int count) {
		this.host = host;
		this.packetSize = packetSize;
		this.count = count;
		this.listenerList = new EventListenerList();
		this.changeListener = new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				firePingEvent(e.getSource().toString());
			}
		};
	}

	public void restart() throws IOException {
		// destory previous ping
		if (null != process) {
			process.removeChangeListener(this.changeListener);
			process.destroy();
			process = null;
		}
		// create ping process
		this.process = new LineBasedProcess(this.createPingCommand());
		this.process.addChangeListener(changeListener);
		this.process.start();
	}

	public void stop() {
		if (null != this.process)
			this.process.destroy();
	}

	public void addPingListener(PingListener l) {
		this.listenerList.add(PingListener.class, l);
	}

	protected void firePingEvent(String pingReply) {
		// Guaranteed to return a non-null array
		Object[] listeners = listenerList.getListenerList();
		// Process the listeners last to first, notifying
		// those that are interested in this event
		PingEvent e = this.parsePingReply(pingReply);
		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == PingListener.class) {
				((PingListener) listeners[i + 1]).reply(e);
			}
		}
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getPacketSize() {
		return packetSize;
	}

	public void setPacketSize(int packetSize) {
		this.packetSize = packetSize;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
}
